#include <iostream>
#include <fstream>
#include <string>
#include "InitialPopulationFactory.h"
#include "Crossover.h"
#include "EnvironmentSelection.h"
#include "MatingSelection.h"
#include "Mutation.h"
#include "LocalSearch.h"
#include "MemeticAlgorithm.h"
using namespace std;

Solution MemeticAlgorithm::Run(){
	string directory = "csv\\data";
	directory += (char)(Evaluation::Times/10 + '0');
	directory += (char)(Evaluation::Times%10 + '0');
	system(string("mkdir " + directory).c_str());
	ofstream fout( directory + '\\' + Evaluation::Name + '_' + _name + '_' + _ipf->GetName() + '_' + _co->GetName() + '_' + _ms->GetName() +
		'_' + _mut->GetName() + '_' + _ls->GetName() + '_' + _es->GetName() + ".csv" );
	_ipf->Create( _population , POPULATION_SIZE );
	_bestSolution = _population[0];
	for( Solution& solution : _population )
	{
		if( solution.getEvaluate() < _bestSolution.getEvaluate() )
		{
			_bestSolution = solution;
		}
	}
	int nowGeneration = 0;
	fout << nowGeneration << ',' << _bestSolution.getEvaluate();
	for( int i = 0 ; i < Evaluation::GetJobNum() ; i++ ){
		fout << ',' << _bestSolution[i];
	}
	fout << endl;

	for( Solution& solution : _population ){
		fout << nowGeneration << ',' << solution.getEvaluate();
		for( int j = 0 ; j < Evaluation::GetJobNum() ; j++ ){
			fout << ',' << solution[j];
		}
		fout << endl;
	}

	while( nowGeneration < _maxGeneration )
	{
		++nowGeneration;
		vector<Solution> childPopulation;
		while( childPopulation.size() < POPULATION_SIZE )
		{
			int last = childPopulation.size();
			_co->Run( childPopulation , _ms->Select( _population ) , _ms->Select( _population ) );
			for( int i = last ; i < childPopulation.size() ; ++i )
			{
				if( rand() % 100 <= 2 ){
					_mut->Mutate( childPopulation[i] );
				}
				Solution localSearchBestSolution = _ls->Run( childPopulation[i] , 0.0001 );
				SetLocalSearchValue( childPopulation[i] , localSearchBestSolution);
				if( localSearchBestSolution.getEvaluate() < _bestSolution.getEvaluate() )
				{
					_bestSolution = localSearchBestSolution;
				}
			}
			_population = _es->Select( _population, childPopulation );
		}

		fout << nowGeneration << ',' << _bestSolution.getEvaluate();
		for( int i = 0 ; i < Evaluation::GetJobNum() ; i++ ){
			fout << ',' << _bestSolution[i];
		}
		fout << endl;

		for( Solution& solution : _population ){
			fout << nowGeneration << ',' << solution.getEvaluate();
			for( int j = 0 ; j < Evaluation::GetJobNum() ; j++ ){
				fout << ',' << solution[j];
			}
			fout << endl;
		}
	}
	fout.close();
	return _bestSolution;
}